home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource2
/
sclib_2
/
2_6
/
v6n6082a.txt
< prev
next >
Wrap
Text File
|
1995-11-01
|
7KB
|
289 lines
\NLETTER\6.6\HERCULE.COD
/* This is a do-nothing program. It draws a lot of circles and it writes
a short line of text, to demonstrate how to operate Hercules monochrome
bit-mapped graphics, including text in graphics mode. */
#include <stdio.h>
void revdot(), writedot(), t_mode(), sleep(), cleardot(),
g_mode(), clearscreen(), g_write(), g_putch(), sw_scr() ;
int inkey();
long sqroot();
#define INDEXPORT 0x3B4
#define CONTROLPORT 0x3b8
#define DATAPORT 0x3b5
#define CONFIGPORT 0x3bf
#define SCR0 0xb0000 /* Absolute address for page 0. */
#define SCR1 0xb8000 /* Absolute address for page 1. */
#define ROMFONT 0xffa6e /* Absolute address of IBM ROM character set. */
#define GC_WIDTH 10 /* Width in pixels of character plus spacing.
It can be as small as 8 or as large as you like.*/
char *font; /* Pointer to character font in ROM. */
#define XSTART 270 /* These set the size of the circle, and its */
#define YSTART 165 /* aspect ratio. */
int gdata[12] = {
0x35, 0x2d, 0x2e, 0x7, 0x5b, 0x2, 0x57, 0x57, 0x2, 0x3, 0x0, 0x0
};
int tdata[12] = {
0x61, 0x50, 0x52, 0xf, 0x19, 0x6, 0x19, 0x19, 0x2, 0xd, 0xb, 0xc
};
int main()
{
long x,y,xs,ys;
int h1,h2,v;
long xaxis,yaxis;
char *abstoptr(); /* Converts absolute address to far pointer. */
char *screen0addr; /* Compiler-dependent far pointer. */
xaxis= XSTART;
yaxis= YSTART;
screen0addr=abstoptr(SCR0);
font=abstoptr(ROMFONT);
clearscreen(screen0addr);
g_mode();
g_write("Circles - KITTENSOFT",330,470,screen0addr);
for(;;){
if (inkey()) break;
xs=xaxis*xaxis;
ys=yaxis*yaxis;
for(y=(-1*yaxis);y<=(yaxis);y+=1){
x=y;
x=( xs - x*x*xs/ys );
if (x<0) continue;
x=sqroot(x);
v=(int)y+174;
h1=(int)x+300;
h2=(int)(-1*x)+300;
revdot(v,h1,screen0addr);
revdot(v,h2,screen0addr);
}
if (xaxis<=8) xaxis--;
else xaxis-=xaxis/8;
if (yaxis<=8) yaxis--;
else yaxis-=yaxis/8;
xs=xaxis*xaxis;
ys=yaxis*yaxis;
for(x=(-1*xaxis);x<=(xaxis);x+=1){
y=x;
y=( ys - y*y*ys/xs );
if (y<0) continue;
y=sqroot(y);
v=(int)x+300;
h1=(int)y+174;
h2=(int)(-1*y)+174;
revdot(h1,v,screen0addr);
revdot(h2,v,screen0addr);
}
if (xaxis<=8) xaxis--;
else xaxis-=xaxis/8;
if (yaxis<=8) yaxis--;
else yaxis-=yaxis/8;
if ((xaxis<1)||(yaxis<1)){
xaxis=XSTART;
yaxis=YSTART;
}
}
clearscreen(screen0addr);
t_mode();
}
void g_mode()
{
int i;
outportb(CONFIGPORT,3);
outportb(CONTROLPORT,0);
for(i=0;i<12;i++){
outportb(INDEXPORT,i);
outportb(DATAPORT,gdata[i]);
}
outportb(CONTROLPORT,2);
sleep();
outportb(CONTROLPORT,10);
}
void clearscreen(seg)
char *seg;
{
unsigned off;
for (off=0;off<32768;off++) seg[off]=0;
}
void t_mode()
{
int i;
outportb(CONTROLPORT,0);
for(i=0;i<12;i++){
outportb(INDEXPORT,i);
outportb(DATAPORT,tdata[i]);
}
outportb(CONTROLPORT,53);
sleep();
outportb(CONTROLPORT,61);
outportb(CONFIGPORT,0);
}
/*
The following functions write, clear, and reverse individual
pixels. seg is the location of the beginning of screen memory. off
is the offset within memory. These functions operate in large model,
where it is possible to write directly to any address in memory.
If your compiler does not support large model, you can get the same
results with the peek() and poke() functions.
This program uses only page 0. You can use page 1 by passing its
address to these functions.
*/
void writedot(y,x,seg)
int x,y;
char *seg;
{
unsigned off;
unsigned char c,bit;
/* Calculate offset of byte within screen memory: */
off=(unsigned)( 0x2000 * (y%4) + 90*(y/4) + x/8 );
/* Get byte presently at that location: */
c=seg[off];
/* or, for compilers without far pointers:
c=peekb(off,seg); */
/* Calculate which bit within the byte to set: */
bit = 1<< (7-x%8);
/* Set the bit: */
c |= bit;
/* Write the altered byte back into memory */
seg[off]=c;
/* or, for compilers without far pointers:
pokeb(off,seg,c); */
}
void cleardot(y,x,seg)
int x,y;
char *seg;
{
unsigned off;
unsigned char c,bit;
off=(unsigned)( 0x2000 * (y%4) + 90*(y/4) + x/8 );
c=seg[off];
bit = 1<< (7-x%8);
c &= ((unsigned char)0xff ^ bit);
seg[off]=c;
}
void revdot(y,x,seg)
int x,y;
char *seg;
{
unsigned off;
unsigned char c,bit;
off=(unsigned)( 0x2000 * (y%4) + 90*(y/4) + x/8 );
c=seg[off];
bit = 1<< (7-x%8);
c ^= bit;
seg[off]=c;
}
/* inkey will vary from one compiler to the next */
int inkey()
{
int k;
k=bdos(0x600,0xff,0);
return(k);
}
long sqroot(n)
long n;
{
long r1,r2;
r1=n;
r2=1;
while (r1>r2){
r1=(r1+r2)/2;
r2=n/r1;
}
return(r1);
}
/* This provides a one-second pause. However, it is
compiler-dependent as clock() does different things under
different compilers. */
void sleep()
{
long a,clock();
a=clock();
while ( clock()-a < 100 )
;
}
/* v can be from 0 to 347 and h can be from 0 to 719.
This simple function breaks off if a line of text reaches
the right hand side of the screen. You can write a more
intelligent function that will wrap around, or even remember
a "cursor position" from one call to the next. */
void g_write(s,v,h,seg)
char *s,*seg;
int v,h;
{
while (*s) {
if (h>712) break;
g_putch(*s++,v,h,seg);
h+= GC_WIDTH;
}
}
/*
As with the bit-mapping functions, the following uses large model
for easier access to the ROM character set. peek() will work
just as well.
*/
void g_putch(c,y,x,seg)
int c,y,x;
char *seg;
{
int i,j;
unsigned char scan_line,mask;
for (i=0;i<8;i++){
scan_line=font[c*8+i];
for (mask=128,j=0;j<8;j++,mask>>=1){
if (scan_line & mask) writedot(y+i,x+j,seg);
else cleardot(y+i,x+j,seg);
}
for (j=8;j<GC_WIDTH;j++)
cleardot(y+i,x+j,seg);
}
}
/* This is not used in this program. It is included for
reference only. If called, it would toggle the display back
and forth between screen 0 and screen 1. */
void sw_scr()
{
static int scr=0;
scr^=128;
outportb(CONTROLPORT, 10 | scr);
}